using System;
using System.Collections;
using System.Collections.Generic;
using Script.StateMachine;
using UnityEngine;

//创建枚举类型，方便所有状态类得到注册
//如果要新增状态，只需要在此添加枚举类型，并放入状态字典中即可
public enum StateType
{
    Idle, Patrol, Chase, React, Attack, Hit, Death
}

//enemy的属性类
[Serializable]
public class Parameter
{
    public int health;
    public float moveSpeed;
    public float chaseSpeed;
    public float idleTime;
    public Transform[] patrolPoints;
    public Transform[] chasePoints;
    public Transform playerTrans;       //player位置信息
    
    [Header("攻击相关")]
    public Transform attackPoint;       //攻击检测范围的圆心
    public float attackArea;            //攻击检测范围半径
    public LayerMask targetLayer;       //player所在的图层
    
    [HideInInspector]
    public  bool isHit;                  //enemy是否收到攻击
    [HideInInspector]
    public  int hitDamage;               //enemy受到的伤害
    [HideInInspector]
    public  int critical;               //被暴击倍率
    public GameObject damageFont;
    [HideInInspector]
    public TextMesh _textMesh;
    public int hitSpeed;
}

public class FSM : MonoBehaviour
{
    private IState currentState;                                                         //当前状态
    private Dictionary<StateType, IState> states = new Dictionary<StateType, IState>(); //状态字典，枚举状态:状态类
    public Parameter parameter;                                                        //enemy的各种属性
    [HideInInspector]
    public Animator animator;
    [HideInInspector]
    public Rigidbody2D rigidbody2D;

    void Start()
    {
        //在字典中注册新的状态，新加状态需要新注册
        states.Add(StateType.Idle, new IdleState(this));            //注册Idle状态
        states.Add(StateType.Patrol, new PatrolState(this));        //注册Patrol状态
        states.Add(StateType.Chase, new ChaseState(this));        
        states.Add(StateType.Attack, new AttackState(this));        
        states.Add(StateType.React, new ReactState(this));    
        states.Add(StateType.Hit, new HitState(this));    
        states.Add(StateType.Death, new DeathState(this));    
        
        animator = gameObject.GetComponent<Animator>();
        rigidbody2D = gameObject.GetComponent<Rigidbody2D>();
        
        TransitionState(StateType.Idle);        //设置初始状态为Idle
    }

    void Update()
    {
        currentState.OnUpdate();                //持续调用当前状态的OnUpdate函数
    }

    //切换状态函数
    public void TransitionState(StateType type)
    {
        if (null != currentState)
            currentState.OnExit();      //执行上一个状态的退出函数
        currentState = states[type];    //使用字典通过枚举找到相应的状态类
        currentState.OnEnter();         //执行新状态的进入函数
    }

    private void OnTriggerEnter2D(Collider2D other)
    {
        //当player进入敌人的视线范围时，得到player的transform信息
        if (other.CompareTag("Player"))
        {
            parameter.playerTrans = other.transform;
            
            //攻击范围内检测到玩家，检测攻击圆心是否在player图层上
            if (Physics2D.OverlapCircle(parameter.attackPoint.position, parameter.attackArea, parameter.targetLayer))
            {
                other.GetComponent<PlayerController>().Attacked(1);
            }
            
        }
        
    }

    private void OnTriggerExit2D(Collider2D other)
    {
        //如果攻击框消失，也会触发这个函数，如果只有底边compareTag一个条件，playerTrans就为空
        //这个时候就不会由攻击state切换追击state（因为追击state有playerTrans才会追） 
        //所以要再加一个判断player是否在攻击范围内的条件（追击框要小于攻击范围检测框）
        if (other.CompareTag("Player") && 
            !Physics2D.OverlapCircle(parameter.attackPoint.position, parameter.attackArea, parameter.targetLayer))
        {
            parameter.playerTrans = null;
        }
    }

    //可在屏幕上绘制图像
    private void OnDrawGizmos()
    {
        Gizmos.DrawWireSphere(parameter.attackPoint.position, parameter.attackArea);//绘制一个圆形图像
    }

    #region 各个状态的通用函数可以写在这里

    //调整enemy朝向player
    public void Flip(Transform target)
    {
        if (target != null)
        {
            if (transform.position.x<target.position.x)
            {
                transform.localScale = new Vector3(1, 1, 1);
            }
            else
            {
                transform.localScale = new Vector3(-1, 1, 1);
            }
        }
        
    }
    
    public void ShowHitText()
    {
        Vector2 showPos = new Vector2(transform.position.x, transform.position.y+(float)0.71);
        GameObject gb = GameObject.Instantiate(parameter.damageFont, showPos, Quaternion.identity);
        parameter._textMesh = gb.transform.GetChild(0).GetComponent<TextMesh>();  //字体为子物体
        parameter._textMesh.text = parameter.hitDamage.ToString();
        if (parameter.critical > 1)
            parameter._textMesh.color = Color.red;
    }


    #endregion
    
}
